package org.club.common.config;

import org.club.Service.ActivityService;
import org.club.common.model.entity.Activity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

@Configuration
public class DynamicActivitySchedulerConfig {

    private static final Logger logger = LoggerFactory.getLogger(DynamicActivitySchedulerConfig.class);

    @Autowired
    private ActivityService activityService;

    private ScheduledExecutorService scheduledExecutorService;
    // 使用两个不同的Map来分别管理开始和结束任务
    private ConcurrentHashMap<Long, ScheduledFuture<?>> startTasks = new ConcurrentHashMap<>();
    private ConcurrentHashMap<Long, ScheduledFuture<?>> endTasks = new ConcurrentHashMap<>();

    @Bean
    public ScheduledExecutorService dynamicActivityScheduler() {
        // 创建一个定时任务线程池，增加线程数以处理更多任务
        scheduledExecutorService = Executors.newScheduledThreadPool(10);

        // 每小时重新加载所有活动并安排任务
        scheduledExecutorService.scheduleAtFixedRate(this::scheduleAllActivities, 0, 1, TimeUnit.HOURS);

        return scheduledExecutorService;
    }

    /**
     * 为所有活动安排开始和结束时间的任务
     */
    private void scheduleAllActivities() {
        try {
            logger.info("开始为所有活动安排开始和结束时间任务...");

            // 取消所有现有任务
            cancelAllTasks();

            Date now = new Date();

            // 获取所有未发布的活动并安排开始任务
            List<Activity> unpublishedActivities = activityService.getAllUnpublishedActivities();
            for (Activity activity : unpublishedActivities) {
                scheduleActivityStartTask(activity, now);
            }
            logger.info("已为{}个未发布活动安排了开始时间任务", startTasks.size());

            // 获取所有已发布的活动并安排结束任务
            List<Activity> publishedActivities = activityService.getAllPublishedActivities();
            for (Activity activity : publishedActivities) {
                scheduleActivityEndTask(activity, now);
            }
            logger.info("已为{}个已发布活动安排了结束时间任务", endTasks.size());

        } catch (Exception e) {
            logger.error("安排活动任务时发生错误: ", e);
        }
    }

    /**
     * 取消所有现有任务
     */
    private void cancelAllTasks() {
        // 取消所有开始任务
        for (ScheduledFuture<?> future : startTasks.values()) {
            if (future != null && !future.isDone()) {
                future.cancel(false);
            }
        }
        startTasks.clear();

        // 取消所有结束任务
        for (ScheduledFuture<?> future : endTasks.values()) {
            if (future != null && !future.isDone()) {
                future.cancel(false);
            }
        }
        endTasks.clear();
    }

    /**
     * 为单个活动安排开始时间的任务
     */
    private void scheduleActivityStartTask(Activity activity, Date now) {
        if (activity.getStartTime() == null || activity.getStatus() != 0) {
            return;
        }

        // 计算延迟时间
        long delay = activity.getStartTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
                - now.getTime();
        if (delay <= 0) {
            // 活动开始时间已到，立即更新状态
            activityService.updateActivityStatus(activity.getId(), 1);
            // 同时安排结束任务
            scheduleActivityEndTask(activity, now);
            return;
        }

        // 安排定时任务
        ScheduledFuture<?> future = scheduledExecutorService.schedule(() -> {
            try {
                logger.info("活动[{}]({})开始时间已到，更新状态为已发布", activity.getId(), activity.getTitle());
                activityService.updateActivityStatus(activity.getId(), 1);

                // 任务完成后从映射中移除
                startTasks.remove(activity.getId());

                // 活动发布后，立即安排结束任务
                Activity updatedActivity = new Activity();
                updatedActivity.setId(activity.getId());
                updatedActivity.setTitle(activity.getTitle());
                updatedActivity.setEndTime(activity.getEndTime());
                updatedActivity.setStatus(1);
                scheduleActivityEndTask(updatedActivity, new Date());

            } catch (Exception e) {
                logger.error("更新活动[{}]开始状态时发生错误: ", activity.getId(), e);
            }
        }, delay, TimeUnit.MILLISECONDS);

        // 保存任务引用
        startTasks.put(activity.getId(), future);
        logger.info("已为活动[{}]({})安排开始时间任务，将在{}开始",
                activity.getId(), activity.getTitle(), activity.getStartTime());
    }

    /**
     * 为单个活动安排结束时间的任务
     */
    private void scheduleActivityEndTask(Activity activity, Date now) {
        if (activity.getEndTime() == null || activity.getStatus() != 1) {
            return;
        }

        // 计算延迟时间
        long delay = activity.getStartTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
                - now.getTime();
        if (delay <= 0) {
            // 活动已经结束，立即更新状态
            activityService.updateActivityStatus(activity.getId(), 4);
            return;
        }

        // 安排定时任务
        ScheduledFuture<?> future = scheduledExecutorService.schedule(() -> {
            try {
                logger.info("活动[{}]({})已结束，更新状态为已结束", activity.getId(), activity.getTitle());
                activityService.updateActivityStatus(activity.getId(), 4);
                // 任务完成后从映射中移除
                endTasks.remove(activity.getId());
            } catch (Exception e) {
                logger.error("更新活动[{}]结束状态时发生错误: ", activity.getId(), e);
            }
        }, delay, TimeUnit.MILLISECONDS);

        // 保存任务引用
        endTasks.put(activity.getId(), future);
        logger.info("已为活动[{}]({})安排结束时间任务，将在{}结束",
                activity.getId(), activity.getTitle(), activity.getEndTime());
    }

    @PreDestroy
    public void destroy() {
        if (scheduledExecutorService != null && !scheduledExecutorService.isShutdown()) {
            logger.info("关闭活动调度器...");
            // 取消所有任务
            cancelAllTasks();

            // 关闭线程池
            scheduledExecutorService.shutdown();
            try {
                if (!scheduledExecutorService.awaitTermination(60, TimeUnit.SECONDS)) {
                    scheduledExecutorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                scheduledExecutorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
}